package cn.cew.bytespyserver.controller;

import cn.cew.bytespyserver.tool.BaseUtils;
import cn.cew.bytespyserver.tool.JarUtils;
import cn.cew.bytespyserver.vm.VmAttach;
import cn.cew.bytespyserver.vm.VmDescriptor;
import cn.cew.bytespyserver.page.ApiResponse;
import cn.hutool.json.JSONUtil;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import javassist.NotFoundException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chenenwei
 * @version 1.0.0
 * @description TODO
 * @createTime 2022-10-13 15:02:00
 */
@Slf4j
@Valid
@Api("byteSpy 接口列表")
@RestController
@RequestMapping("/api/v1")
public class ByteSpyController {

    @ApiOperation("查询java虚拟机列表")
    @GetMapping("/listVm")
    public ApiResponse<VmDescriptor> listVm (String name) {
        return ApiResponse.success(VmAttach.listVirtualMachine(name));
    }

    @ApiOperation("查询类列表")
    @GetMapping("/listClass")
    public ApiResponse<List<ClassInfo>> listClass (String jarPath, String prefix) throws IOException {
        return ApiResponse.success(JarUtils.listClass(jarPath, prefix));
    }

    @ApiOperation("查询方法列表")
    @GetMapping("/listMethod")
    public ApiResponse<List<MethodInfo>> listClass (String jarPath, String packageName, String className) throws Exception {
        return ApiResponse.success(JarUtils.listMethod(jarPath, packageName, className));
    }

    @ApiOperation("查询类代码块")
    @GetMapping("/getClassCodeBlock")
    public ApiResponse<MethodCode> getClassCodeBlock (String packageName, String className) throws IOException, ClassNotFoundException {

        return ApiResponse.success(JarUtils.getClassCodeBlock(packageName, className));
    }

    @ApiOperation("查询方法代码块")
    @GetMapping("/getMethodCodeBlock")
    public ApiResponse<MethodCode> getMethodCodeBlock (String packageName, String className, String methodName, String params) throws IOException, ClassNotFoundException {

        String javaFilePath = BaseUtils.getProjectPath(File.separator + "tempJava" + File.separator + packageName + "." + className + ".java");
        return ApiResponse.success(JarUtils.getMethodCodeBlock(javaFilePath, methodName, BaseUtils.toList(params, ",")));
    }

    @ApiOperation("执行代理")
    @PostMapping("/exec")
    public ApiResponse<Boolean> exec (@Validated @RequestBody CmdParam cmdParam) throws IOException {

        log.info("【attach 参数】 {}", JSONUtil.toJsonStr(cmdParam));
        String cmd = cmdParam.getCmd();
        VmAttach.attach(cmdParam.getPid(), cmdParam.getJarFile(), cmd);
        return ApiResponse.success(true);
    }

    @ApiOperation("类型")
    @PostMapping("/type")
    public ApiResponse<List<Operator>> type () throws IOException {

        List<Operator> list = new ArrayList<>(2);
        list.add(new Operator("1", "打印参数"));
        list.add(new Operator("2", "修改方法返回值"));
        list.add(new Operator("3", "自定义代码"));
        return ApiResponse.success(list);
    }

    @ApiOperation("操作类型")
    @PostMapping("/operator")
    public ApiResponse<List<Operator>> operator (String type) throws IOException {
        List<Operator> list = new ArrayList<>(2);
        if (type.equals("1")) {
            list.add(new Operator("0", "参数"));
            list.add(new Operator("1", "返回值"));
            list.add(new Operator("2", "全局变量"));
            list.add(new Operator("3", "局部变量"));
            list.add(new Operator("4", "方法耗时"));
            return ApiResponse.success(list);
        } else if (type.equals("2")) {

        } else if (type.equals("3")) {

        }
        return ApiResponse.success(true);
    }


}
